//destribes the terrain of a game.
#include "UTerrain.h"
#include <SDL/SDL_image.h>
#include "../UTextureManager.h"
#include "../UModel.h"
#include "UUnitOrBuildingType.h"
using namespace std;

TVector LightPos =  TVector(0,500,1000);

TVector TTerrain::GetNormalOfFace(int x, int y)
{
	TVector hulp1	= TVector(x  , y+1, HeightMapData[x  ][y+1])- TVector(x, y, HeightMapData[x][y]);
	TVector hulp2	= TVector(x+1, y  , HeightMapData[x+1][y  ])- TVector(x, y, HeightMapData[x][y]);

	hulp1 = (hulp2 * hulp1);
	hulp1.Normalize();
	return  hulp1;
}

float TTerrain::HeightAtPos(int X, int Y) const
{
	if (X>0 && X<width && Y>0 && Y<height)
		return HeightMapData[X][Y];
	return -1;
}


TTerrain::TTerrain(string HeightmapName, string ColorMapName)
{
	SDL_Surface* HeightMap = IMG_Load(("Data/Info/Maps/"+HeightmapName+".png").c_str());
	SDL_Surface* ColorMap  = IMG_Load(("Data/Info/Maps/"+ColorMapName +".png").c_str());

	width  = HeightMap->w;
	height = HeightMap->h;
	SDL_LockSurface(HeightMap);


	HeightMapData   .resize((boost::extents[width][height]));
	HeightMapNormals.resize((boost::extents[width][height]));

	for (int x=0; x< width; ++x)
	{
		for (int y=0; y<height; ++y)
		{
			int val = ((uint8*)(HeightMap->pixels))[3*(x + y*width)];
			HeightMapData[x][y] = float(val)/5;
		}
	}

	SDL_FreeSurface(HeightMap);

	for (int x=0; x< width-2; ++x)
	{
		for (int y=0; y<height-2; ++y)
		{
			HeightMapNormals[x][y] =
				(
				GetNormalOfFace(x  , y  )+
				GetNormalOfFace(x+1, y  )+
				GetNormalOfFace(x+1, y+1)+
				GetNormalOfFace(x  , y+1)
				)/4;
		}
	}
	
}


bool TTerrain::IsFlat(int X, int Y)
{
  return (HeightMapNormals[X-1][Y-1].x==0 && HeightMapNormals[X-1][Y-1].y==0);
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////
void TGUITerrain::PushVectorColor(int x, int y, std::vector<uint32>* ColArray)
{
	TVector DistanceV= LightPos- TVector(x, y, Terrain->HeightAtPos(x, y ));
	DistanceV.Normalize();
	float fX  = max(min( (Terrain->HeightMapNormals[x][y]% DistanceV), 1.0f), 0.0f);
	uint8 X = fX*255;
	ColArray->push_back((X<<16)+(X<<8)+X);
}

TGUITerrain::TGUITerrain(TTerrainRefConst terrain)
{
	Terrain = terrain;

	int width  = Terrain->Width();
	int height = Terrain->Height();

	if (glBindBufferARB && glGenBuffersARB && glBufferDataARB) {
		vector<TVector> PVertices;
		vector<uint32> PColors;

		/* stop dingen in pvvertices */
		for (int x=0; x< width-3; ++x)
		{
			for (int y=0; y<height-3; ++y)
			{
				PVertices.push_back(TVector(x, y, terrain->HeightAtPos(x, y )));
				PushVectorColor(x, y, &PColors);
	
				PVertices.push_back(TVector(x+1, y, terrain->HeightAtPos(x+1,y  )));
				PushVectorColor(x+1, y, &PColors);
	
				PVertices.push_back(TVector(x+1, y+1, terrain->HeightAtPos(x+1,y+1  )));
				PushVectorColor(x+1, y+1, &PColors);
	
				PVertices.push_back(TVector(x, y+1, terrain->HeightAtPos(x ,y+1  )));
				PushVectorColor(x, y+1, &PColors);
			}
		}
	
		nVertexCount = PVertices.size();
	
		glGenBuffersARB( 1,&nVBOVertices);
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVBOVertices);
		glBufferDataARB(GL_ARRAY_BUFFER_ARB, nVertexCount * sizeof(PVertices[0]), &PVertices[0], GL_STATIC_DRAW_ARB);
	
		glGenBuffersARB(1,&nVBOColors);
		glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVBOColors);
		glBufferDataARB(GL_ARRAY_BUFFER_ARB, nVertexCount * sizeof(PColors[0]), &PColors[0], GL_STATIC_DRAW_ARB);
	}
}


void TGUITerrain::Draw()
{
	MyDraw();
	glDisable(GL_BLEND);
}

void TGUITerrain::MyDraw()
{

	int width  = Terrain->Width();
	int height = Terrain->Height();

	glDisable(GL_TEXTURE_2D);
	glColor3f(1,1,1);

	//glBindTexture(GL_TEXTURE_2D, ColorMapTexture);
	if (glBindBufferARB && glGenBuffersARB && glBufferDataARB)
	{
		glDisable(GL_LIGHTING);
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);

		glBindBufferARB(GL_ARRAY_BUFFER_ARB,nVBOVertices);
		glVertexPointer(3,GL_FLOAT,0,NULL);

		glBindBufferARB(GL_ARRAY_BUFFER_ARB,nVBOColors);
		glColorPointer(4, GL_UNSIGNED_BYTE,0, NULL);

		glDrawArrays(GL_QUADS,0,nVertexCount);

		glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);
	}
	else
	{
		glEnable(GL_LIGHTING);
		glBegin(GL_QUADS);
		for (int x=0; x< width-1; ++x)
		{
			for (int y=0; y<height-1; ++y)
			{
				 glNormal3fv(&Terrain->HeightMapNormals[x][y].x);
				 glVertex3f(x		, y		, Terrain->HeightAtPos(x,y  ));

				 glNormal3fv(&Terrain->HeightMapNormals[x+1][y].x);
				 glVertex3f(x+1		, y		, Terrain->HeightAtPos(x+1,y  ));

				 glNormal3fv(&Terrain->HeightMapNormals[x+1][y+1].x);
				 glVertex3f(x+1		, y+1	, Terrain->HeightAtPos(x+1,y+1));

				 glNormal3fv(&Terrain->HeightMapNormals[x][y+1].x);
				 glVertex3f(x		, y+1	, Terrain->HeightAtPos(x,y+1));
			}
		}

		glEnd();
	}



	glEnable(GL_LIGHTING);

}
